from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse, JsonResponse
from core.service import *
from core.log import logging
from filters.exclude import filter_checked
from filters import AppMiddlewareMixin
from core.config import cfg, BASE_ALLOWED_HOSTS, REQUEST_MANAGER, attribute,TOKEN_MANAGE
from core.RPC import REMOTE_SERVICE
from core.token.token_event import TOKEN_EVENT
from core.token.token_cache import Token_Cache


def checkAllow(m_token, ip,  handle):
    '''
        检查白名单
    '''
    if (ip in BASE_ALLOWED_HOSTS) or (BASE_ALLOWED_HOSTS[0] == '*'):
        if m_token:
            if m_token != cfg.SERVICE_ACCESS_SECRET:
                handle.error_update("VALIDATE_TOKEN", "token error.")
        else:
            handle.error_update("VALIDATE_TOKEN", "token is none.")
    else:
        handle.error_update(
            "ALLOW_IP", "'%s' can not access service, please checked." % ip)


class AclMiddleware(AppMiddlewareMixin):

    def process_request(self, request):
        try:
            if not cfg.DEBUG:  # 调试期间不做Token判断.
                if filter_checked(request):  # 检查是否要需要检查token
                    m_header_manage= TOKEN_MANAGE()
                    m_header_manage.load(request)
                    if not m_header_manage.SAAS_ACCESS_SOURCE.exists:
                        m_header_manage.SAAS_ACCESS_SOURCE = "default"
                    if m_header_manage.SAAS_API_TOKEN.exists:
                        m_source = m_header_manage.SAAS_ACCESS_SOURCE.value.lower()
                        if not m_source:
                            m_source = "default"
                        if m_source == "rpc_reversal":
                            self.validate_genernal_token(
                                m_header_manage.SAAS_API_TOKEN.value, request)
                        elif m_source == "rpc":
                            self.validate_dynamic_token(
                                m_header_manage.SAAS_API_TOKEN.value, request)
                        elif m_source == "default":
                            self.validate_local_token(
                                m_header_manage.SAAS_API_TOKEN.value)
                    else:
                        self.error_update('VALIDATE_TOKEN', 'miss token.')

                    if not self.state:
                        return JsonResponse({"state": 500, "msg": self.error_message})
        except Exception as e:
            logging.error(e)
            return JsonResponse({"state": 500, "msg": e.args(1)})

    def validate_genernal_token(self, v, rq):
        try:
            m_api_token = v
            m_remote_addr = REQUEST_MANAGER.getRemoteAddr(rq)
            if m_api_token:
                checkAllow(m_api_token, m_remote_addr, self)
        except Exception as e:
            self.error_update("VALIDATE_TOKEN", e.args)

    def validate_local_token(self, v, rq):
        state, data = Token_Cache.validate_token(
            token=v,
            event=TOKEN_EVENT.APP_ACCESS,
            remote_ip=REQUEST_MANAGER.getRemoteAddr(rq)
        )
        if not state:
            self.error_update("VALIDATE_LOCAL_TOKEN",data)

    def validate_dynamic_token(self, v: str, rq):
        try:
            result= REMOTE_SERVICE.RPC_CENTER.VALIDATE_RPC_TOKEN_GET(v)
            if result:
                if result["state"]!=200:
                    self.error_update("VALIDATE_DYNAMIC_TOKEN","validate_dynamic_token:token event(%s), error(%s)."%(TOKEN_EVENT.RPC_ACCESS, str(result['msg'].args) if isinstance(result['msg'],Exception) else result["msg"]))
            else:
                self.error_update("VALIDATE_DYNAMIC_TOKEN","rpc validate return None.")
        except Exception as e:
            self.error_update("VALIDATE_DYNAMIC_TOKEN",str(e.args))

    def validate_app_token(self, v: attribute):
        try:
            if REMOTE_SERVICE:
                if REMOTE_SERVICE.DEVELOPER:
                    if REMOTE_SERVICE.DEVELOPER.APP_VALIDATE_APP_ACCESS_TOKEN:
                        result = REMOTE_SERVICE.DEVELOPER.APP_VALIDATE_APP_ACCESS_TOKEN(**{
                            "headers": {
                                v.key: v.value
                            }
                        }
                        )
                        if not result["state"] == 200:
                            self.error_update(
                                "VALIDATE_TOOKEN", "Unauthorized")
                    else:
                        logging.error(
                            "REMOTE_SERVICE.DEVELOPER not found APP_VALIDATE_APP_ACCESS_TOKEN method.")
                        self.error_update("VALIDATE_TOOKEN", "Unauthorized")
                else:
                    logging.error("REMOTE_SERVICE not found DEVELOPER module.")
                    self.error_update("VALIDATE_TOOKEN", "Unauthorized")
            else:
                logging.error("REMOTE_SERVICE is none.")
                self.error_update("VALIDATE_TOOKEN", "Unauthorized")
        except Exception as e:
            logging.error(e)
            self.error_update("VALIDATE_TOOKEN", "Unauthorized")

    def process_response(self, request, response):
        return response

    def process_exception(self, request, exception):
        pass

    def process_template_response(self, request, response):
        return response
